﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
/*
* 知识点一：while循环
while(表达式)
{
循环体;
}
1.当while循环里的表达式为真时，进入循环体，如果为假，则不会执行
2.当表达式恒成立时，会进入死循环
3.如果循环体只有一条语句，则大花括号可以省略,多条语句不能省略

知识点二：do-while循环
do
{
语句;

}
while(表达式);
1.注意do-while循环里的while要加分号，要加分号，
2.do-while循环是先执行后判断条件


知识点三：for循环
for(表达式1;表达式2;表达式3)
{
语句;

}
1.表达式1为初始条件，只执行一次；
2.表达式2为循环条件,判断循环是否继续，循环前执行，循环多少次，就执行多少次
3.表达式3为调整语句，循环后执行，循环多少次，就执行多少次
4.表达式可以省略不写，不过之间的分号不可以省略


知识点五：循环嵌套语句
for(表达式1;表达式2;表达式3;)
{
    for(表达式1;表达式2;表达式3)
     {
     语句块;

     }
}
1.外层循环执行一次，内层循环执行所有次

知识点六：循环控制语句break和continue语句
  1.continue用于结束当前循环次数，并不会跳出整个循环，且continue语句后面的内容
  不会被执行，

  2.break用于跳出当前循环，如果有两层for循环，内层循环中使用了break，那么它
  只会跳出内层循环，并不会跳出外层循环


*/


//打印0-10的数
//int main()
//{
//	int i = 0;
//	while (i<=10)
//	{
//		printf("%d\n", i);
//		i++;
//	}
//	return 0;
//}

//do-while循环打印0-10的数
//int main()
//{
//	int i = 0;
//	do
//	{
//		printf("%d\n", i);
//		i++;
//
//	} while (i <= 10);
//
//	return 0;
//}



//do-while循环打印0-10的偶数
//int main()
//{
//	int i = 0;
//	do
//	{
//		if (i % 2 == 0)
//		{
//			printf("%d\n", i);
//		}
//		i++;
//	} while (i <= 10);
//	return 0;
//}


//whilie循环打印0-10的偶数
//int main()
//{
//	int i = 0;
//	while (i <= 10)
//	{s
//		if (i % 2 == 0)
//		{
//			printf("%d\n", i);
//			
//		}
//		i++;
//	}
//	return 0;
//}


//for循环打印0-10的数
//int main()
//{
//	int i = 0;
//	for (;i<=10;i++)
//	{
//		printf("%d\n", i);
//
//	}
//	return 0;
//}

//用for循环输出0-10之间的偶数
//int main()
//{
//    int i = 0;
//    for (i=0;i<=10;i++)
//    {
//        if (i % 2 == 0)
//            printf("%d\n", i);
//        i++;
//    }
//    return 0;
//}


//用循环嵌套示例:   判断结果最终有几行hello
/*
当i=0时，满足第一层for循环的条件，于是进入第二层for循环，此时j=0，也满足循环条件，
开始打印hello,打印完后,j++，此时并不会跳出内层循环，它会把当前的所有循环次数执行
完，才会跳出循环


*/
//int main()
//{
//    int i, j;
//    for (i=0;i<3;i++)
//    {
//        for (j=0;j<4;j++)
//        {
//            printf("hello\n");
//        }
//    }
//
//    //最终有12行hello，也就是一组4行，共有3组
//    return 0;
//}


//打印5行三列*
//int main()
//{
//    int i, j ;
//    for (i = 0; i < 5; i++)
//    {
//        for (j = 0; j < 3; j++)
//        {
//            printf("*");
//
//        }
//        printf("\n");
//    }
//    return 0;
//}


//continue示例
//int main()
//{
//    int i;
//    for (i=0;i<=10;i++)
//    {
//        if (i == 6)
//        continue;
//        //当i==6时，就不会打印continue后面的语句内容了，它会跳到i++，然后再判断
//        //是否小于等于10
//        printf("%d\n", i);
//    }
//    return 0;
//}


//break示例
//int main()
//{
//    int i, j;
//    for (i=0;i<3;i++)
//    {
//        for (j=0;j<4;j++)
//        {
//           // if (j == 2)
//             //   break;
//            //本来是打印三行四列，但是在第二层for循环中，添加了判断，
//            //如果j==2就会跳出循环，这就导致只会打印两列
//            printf("*");
//
//        }
//        printf("\n");
//    }
//    return 0;
//}


//两层for循环都添加break
//int main()
//{
//    int i, j;
//    for (i=0;i<3;i++)
//    {
//        if (i == 1)
//            break;
//        //外层循环中添加的break，导致只打印1行
//
//        for (j=0;j<4;j++)
//        {
//            if (j == 2)
//               break;
//            //本来是打印三行四列，但是在第二层for循环中，添加了判断，
//            //如果j==2就会跳出循环，这就导致只会打印两列
//            printf("*");
//
//        }
//        printf("\n");
//    }
//    return 0;

//int main()
//{
//    int i;
//    i = 0;
//    do 
//        printf("%d", i);
//    while (i++);
//    printf("%d\n", i);
//    return 0;
//}

//int main()
//{
//	int x = 8;
//	for (; x > 0; x--)
//	{
//		if (x % 3)
//			
//		{
//			printf("%d,", x--);
//		
//				continue;
//		}
//		printf("%d,", --x);
//	}
//	return 0;
//}



//编程程序计算s=1+2+3+4+⋯前50项之和。
/*
一般像计算某某之和，都是有个规律，要定义一个存储和的变量，一般定义s,
本题可以利用for循环，定义一个变量i,这个i是不断变化的，每循环一次，就把新的s加上新的i赋值给s
*/
//int main()
//{
//    int i = 1;
//    int s = 0;
//    for (i=1;i<=50;i++)
//    {
//        s = s + i;
//    }
//    printf("%d\n", s);
//
//    return 0;
//}


//编程程序计算s=1+1/2+1/3+1/4+⋯前50项之和。
/*
这题解决思路和1+2+...+50哪一题是差不多的思路，主要的变化就在于变成了分数，还有就是最后存储和的变量s，他要定义
成浮点型，因为这些1/2  1/3的结果都是小数；还有就是变量i也发生了变化，之前都是1-50的数字，现在是1/2，1/3，可以
看出，分子一直没有发生变化，分母一直在发生变化，所以我们只需要将变量i改成1/i的形式，

第一步：定义float类型的变量s
第二步：定义变量i，这个i是代表分母
第三步：进入for循环
第四步：将s+1.0/i的值赋给s
第五步：一直循环，直到50次循环完为止
*/
//int main()
//{
//    float s=0.0;
//    int i;
//    for (i=1;i<=50;i++)
//    {
//        s = s + 1.0/ i;
//        //s=s+1/i
//        //因为1/i是整除，所以最后得到的结果一定是整数，那么1/2，1/3......都是结果为0，很明显是错的，要想得到小数
//        //那么被除数和除数之间一定要有个是浮点数类型的
//    }
//    printf("和是：%f\n", s);
//    return 0;
//}


//有一分数序列：s=1+2/1+3/2+5/3+8/5+⋯   求出这个数列的前20项s之和
/*
思路和上面两题大差不差，还是求和，只不过这次只用求20项，还是分数序列，所以s还是浮点数类型
那么这题的规律是前一项的分母是后一项的分子，前一项的分母分子之和是后一项的分母
由于这一题跟上面的题发生变化了，i不是有顺序的递增了，所以我们要定义一个fm fz的变量，谨记上一题的教训，
所以这一次我们干脆把fm  fz都定义成float类型




*/

//整体思路没错，但有一些bug
//int main()
//{
//    float s = 0.0;
//    int i = 0;
//    float fm=1.0, fz = 1.0;
//    for (i=1;i<=20;i++)
//    {
//        s = s + fm / fz;
//        fz= fm + fz;
//        //但是这样写就有问题，因为fm=1.0  fz=1.0  fz=fm+fz=2.0
//        fm = fz;
//        //fm=2.0他应该是等于旧的分子，而不是新的分子，应该等于1.0而不是2.0，那么显然这一步存在问题
//     
//    }
//    printf("%f\n", s);
//    return 0;
//}

//int main()
//{
//    float s = 0.0;
//    int i = 0;
//    float fm=1.0, fz = 1.0;
//    for (i=1;i<=20;i++)
//    {
//        s = s + fm / fz;
//        fm = fz;
//        //fm=1.0
//        //fm=fz=2
//        fz = fm + fz;
//        //fz=1.0+1.0=2.0
//        // fz=fm+fz=2+2=4
//        //即使了调整顺序，也不行，
//     
//    }
//    printf("%f\n", s);
//    return 0;
//}

//正确写法：
//int main()
//{
//   
//    float s = 0.0;
//    float fm=1.0,fz=1.0, t;
//    int i;
//   
//    for (i=1;i<=20;i++)
//    {
//        s = s + fz / fm;
//        //s=0+1.0/1.0
//        //s=1+2.0/1.0
//        t = fz;
//        //t=1.0
//        // t=2.0
//        //借助中间值变量t存储旧的分子
//        fz = fm + fz;
//        //fz=1.0+1.0=2.0
//        //fz=2.0+1.0=3.0
//        fm = t;
//        //fm=1.0
//        //fm=2.0
//        //分母应该等于旧的分子，而不是最新的分子
//
//    }
//    printf("%f\n", s);
//    return 0;
//}


//求1000以内的完数
/*
完数的定义：完数就是一个数的因子之和恰好等于这个数本身，比如6的因子因子是1，2，3，1+2+3=6，
因子：就是所有能够被某个数整除且不产生余数的数，但是某个数的因子不包含它本身，假设一个数是i，拿i-1，从1到i-1所有的数字去
整除i，再把因子相加，看因子之和是不是等于这个数本身，如果是，就是完数

1.首先这题要搞两层for循环，第一层负责完成1-1000的数自增，不断产生新的数，那我们就定义一个i变量，i的初始值为1，一共循环1000次，
因为要判断到1000为止嘛，为什么i的初始值不为0，是因为0不是完数，0不是完数；

2.我们要对每一个i值都进行判断，判断他是不是完数，那怎么判断是不是完数呢？这一步是怎么操作的呢？
首先每产生了一个新的i后，就拿1到i-1的数去整除，如果能整除，就说明是i的因子，把所有的因子加起来，这时候我们又需要定义一个变量
s,它用来存储每次因子相加的和，最后再拿i去和所有的因子之和进行比较，如果相等，说明是完数，

那1到i-1的数字也是发生变化的，所以我们要定义一个j变量，用i去整除j

第二层for循环主要是负责产生1到i-1的数，判断是不是因子，是就存储到变量s里，第二层循环结束了，
再拿相加之和去和i进行比较

*/
int main()
{
    int i, j;
    int s;
    //int s = 0;
    //注意：变量s初始化不要在循环外面初始化，如果在外面初始化，那么每一次循环结束后，就会保留上一个i产生的因子之和
    //这明显是不对的，因为每一次s都要从0开始，重新计算
    for (i=1;i<=1000;i++)
        //第一层for循环负责让i发生变化
    {
       s = 0;
        //所以把s在循环里面初始化比较合适
        for (j=1;j<i;j++)
        {
            //s = 0;
            if (i % j == 0)
            {
               // s = s + j;
                s+=j;

            }
        }
        if (i == s)
        {
            printf("%d\n", s);
           // printf("%d\n", i);
       
        }


    }


    return 0;
}